package com.infrared5.util
{
	import com.infrared5.error.ModelReferenceError;
	import com.infrared5.model.Model;
	
	import flash.utils.getDefinitionByName;
	import flash.utils.getQualifiedClassName;

	public class ModelObjectUtil
	{
		/**
		 * Utility method to inflate a generic Object back to a Model instance based on supplied class name. 
		 * @param value Object The Generic Object.
		 * @param clazz String The fully-qualified classname.
		 * @return Model The typed Model instance.
		 * 
		 * @throws ReferenceError ReferenceError will be thrown if Class related to clazz is not compiled into SWF - from getDefinitionByName().
		 * @throws ModelOperationError ModelOperationError is thrown if the Object instance created from clazz is not of base-type Model.
		 */
		public static function createFromObject( value:Object, clazz:String ):Model
		{
			var model:Model = new ( getDefinitionByName( clazz ) as Class ) as Model;
			// Check on model validity.
			if( model == null )
			{
				// If null, something has gone wrong in creating a typed Model instance.
				//	Most likely, you should check that the class is a subclass of Model.
				throw new ModelReferenceError( "Cannot create a typed Model instance using " + clazz + " as a qualified class name. " +
												"Please make sure that " + clazz + " is a subclass of Model." );
			}
			// Else, we have our new Model instance, let's fill it.
			var description:Vector.<String> = model.description;
			var property:String;
			for( property in value )
			{
				if( description.indexOf( property ) != -1 )
				{
					model[property] = value[property];
				}
			}
			return model;
		}
		
		/**
		 * Returns flag of two Models being similar, meaning they are of the same class type with similar (not strict in reference) property values. 
		 * @param oneModel Model
		 * @param anotherModel Model
		 * @return Boolean
		 */
		public static function isModelsSimilar( oneModel:Model, anotherModel:Model ):Boolean
		{
			var description:Vector.<String>;
			var property:String;
			
			description = oneModel.description;
			// First check if their descriptions are strictly equal.
			// This will return true if they are the same class type as that is cached on Model based on classname.
			if( anotherModel.description !== description )
			{
				return false;	
			}
			// Then test less strictly on property values for similarity.
			for each( property in description )
			{
				if( oneModel[property] != anotherModel[property] )
				{
					return false;
				}
			}
			// If we made it this far, they can be considered similar.
			return true;
		}
	}
}